<template>
  <div class="executor-main">
    <el-container direction="vertical">
      <!-- 应用启动信息 -->
      <el-container direction="vertical">
        <el-main class="args user">
          <img src="https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif" alt="User" class="user-avatar">
          <div class="content-wrapper">
            <strong class="bold-text">{{ $t('launch') }}{{ $t('application') }}：</strong>{{ this.appName }}
          </div>
        </el-main>
      </el-container>

      <!-- 循环展示每一步任务的用户输入和执行结果 -->
      <div v-for="(step, index) in executionSteps" :key="index">
        <!-- 用户输入 -->
        <el-container v-if="hasInputArgs(step)">
          <!--        <el-container>-->
          <el-main v-if="step.tool_name && !step.canceled">
            <div style="overflow: hidden;">
              <img :src="getImageUrl()" alt="元芳" style="float: right" class="yuanfang-avatar">
            </div>
            <div style="clear: both;" />
            <div>
              <div class="content-wrapper">
                <div v-if="tasks.length">
                  <div v-for="task in tasks" v-if="task.task_id === step.task_id" :key="task.id">
                    {{ $t('sub') }}{{ $t('task') }}{{ index + 1 }}：{{ task.task }}
                  </div>
                </div>
                {{ $t('tool') }}：{{ step.tool_name }}
              </div>
              <el-form v-if="index === nowOnTask" class="content-wrapper" @submit.native.prevent="submitForm">
                <div v-for="(arg, argIndex) in step.userInput" :key="argIndex">
                  <div v-if="arg.source === 'input'">
                    <template v-if="arg.input.options">
                      <template v-if="isSingleChoice(arg.input.options)">
                        <el-form-item :label="arg.input.prompt">
                          <br>
                          <div v-for="(option, optionIndex) in arg.input.options" :key="optionIndex">
                            <el-radio v-model="arg.value" :label="option.value">{{ option.name }}</el-radio>
                          </div>
                        </el-form-item>
                      </template>
                      <template v-else>
                        <el-form-item :label="arg.input.prompt">
                          <br>
                          <div v-for="(option, optionIndex) in arg.input.options" :key="optionIndex">
                            <el-checkbox v-model="arg.value" :label="option.value">{{ option.name }}</el-checkbox>
                          </div>
                        </el-form-item>
                      </template>
                    </template>
                    <template v-else>
                      <el-form-item :label="arg.input.prompt">
                        <el-input
                          v-if="arg.input.inputMode === 'singleLine'"
                          v-model="arg.value"
                          v-focus="argIndex === 0"
                          @keyup.enter="submitForm"
                        />
                        <el-input
                          v-if="arg.input.inputMode === 'mulitiLine'"
                          v-model="arg.value"
                          v-focus="argIndex === 0"
                          type="textarea"
                          @keyup.enter="submitForm"
                        />
                      </el-form-item>
                    </template>
                  </div>
                  <div v-if="arg.source === 'file'">

                    <el-form-item>
                      <el-upload
                        :http-request="uploadFile"
                        :before-remove="beforeRemoveFile"
                        drag
                        :limit="1"
                        :on-exceed="handleExceed"
                        :first-list="fileList"
                        style="margin-top: 15px"
                      >
                        <i class="el-icon-upload" />
                        <div class="el-upload__text">{{ $t('Drag_file_tips') }}<em>{{ $t('click') + $t('upload') }}</em>
                        </div>
                      </el-upload>
                    </el-form-item>
                  </div>
                </div>
                <el-form-item style="text-align: center">
                  <el-button type="primary" @click="submitForm">{{ $t('submit') }}</el-button>
                  <el-button @click="cancelExecution(index)">{{ $t('cancel') }}</el-button>
                </el-form-item>
              </el-form>
            </div>
          </el-main>
          <el-main v-if="step.canceled">
            <div style="overflow: hidden;">
              <img :src="getImageUrl()" alt="元芳" style="float: right" class="yuanfang-avatar">
            </div>
            <div style="clear: both;" />
            <div class="content-wrapper">
              {{ $t('user_terminated_execution_tip') }}
            </div>
          </el-main>
        </el-container>

        <!-- 用户输入的展示 -->
        <el-container v-if="index < nowOnTask && hasInputArgs(step)">
          <!--        <el-container v-if="index < nowOnTask ">-->
          <el-main>
            <img src="https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif" alt="User" class="user-avatar">
            <div v-if="allUserInputs[index]">
              <div class="content-wrapper">
                <div v-if="tasks.length">
                  <div v-for="task in tasks" v-if="task.task_id === step.task_id" :key="task.id">
                    {{ $t('sub') }}{{ $t('task') }}{{ index + 1 }}：{{ task.task }}
                  </div>
                </div>
                {{ $t('tool') }}：{{ step.tool_name }}
                <div v-for="(value, key, paramIndex) in allUserInputs[index]" v-if="key !== 'tool_name'" :key="key">
                  {{ $t('parameter') }}{{ paramIndex + 1 }}: [{{ value.type }}] {{ value.value }}
                </div>
              </div>
            </div>
          </el-main>
        </el-container>

        <!-- 执行结果 -->
        <el-container v-if="index < nowOnTask">
          <el-main>
            <div style="overflow: hidden;">
              <img :src="getImageUrl()" alt="元芳" style="float: right" class="yuanfang-avatar">
            </div>
            <div style="clear: both;" />
            <template v-if="executeLogs[index]">
              <div class="content-wrapper">
                <div v-if="tasks.length">
                  <div v-for="task in tasks" v-if="task.task_id === step.task_id" :key="task.id">
                    {{ $t('sub') }}{{ $t('task') }}{{ index + 1 }}：{{ task.task }}[{{ step.tool_name }}]{{ $t('has_run')
                    }}
                  </div>
                </div>
              </div>
              <div class="content-wrapper">
                <div v-if="tasks.length">
                  <div v-for="task in tasks" v-if="task.task_id === step.task_id" :key="task.id">
                    {{ $t('sub') }}{{ $t('task') }}{{ index + 1 }}：{{ task.task }}[{{ step.tool_name }}]{{ $t('of') }}{{
                      $t('response_value') }}
                  </div>
                </div>
                <json-viewer :value="executeLogs[index]" />
              </div>
              <div :id="`chart-${index}`" style=" height: 500px;" class="content-wrapper" />
              <div :id="`text-${index}`" style="display: none;" class="content-wrapper" />
            </template>
          </el-main>
        </el-container>
      </div>

      <!-- 错误消息展示 -->
      <el-container v-if="errorMessage">
        <el-main>
          <div style="overflow: hidden;">
            <img :src="getImageUrl()" alt="元芳" style="float: right" class="yuanfang-avatar">
          </div>
          <div style="clear: both;" />
          <div class="content-wrapper">
            哎呀，看起来元芳遇到了个小坎坷！
            <a @click="toggleErrorLog">[错误日志]</a>
            <div v-if="showErrorLog">{{ errorMessage }}
            </div>
          </div>
        </el-main>
      </el-container>

      <!-- 任务执行完毕后显示元芳图标和“已运行完毕！” -->
      <el-container v-if="executionCompleted">
        <el-main>
          <div style="overflow: hidden;">
            <img :src="getImageUrl()" alt="元芳" style="float: right" class="yuanfang-avatar">
          </div>
          <div style="clear: both;" />
          <div ref="completionMessage" class="content-wrapper">
            “{{ this.appName }}”{{ $t('finished_running') }}
          </div>
          <div class="button-container">
            <el-button @click="restartExecution">{{ $t('re_run') }}</el-button>
          </div>
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>

<script>
import { getAppDetail, executeAppStep, getExecutroMemoryBus, processOutput } from '@/api/executor'
import { getWorkflow } from '@/api/workflow'
import jsonEdit from '@/components/AppCreate/task/jsonEdit.vue'
import outputEdit from '@/components/AppCreate/output/outputEdit.vue'
import * as echarts from 'echarts'
import { uploadFile } from '@/api/tool'

export default {
  components: { jsonEdit, outputEdit },
  data() {
    return {
      memoryBusData: {}, // 用来存储不同 taskNum 对应的 memoryBus 数据
      imageId: 0, // 图片ID，初始值为0
      appDetail: {},
      appName: '',
      nowOnTask: 0,
      nowTaskContent: {},
      nowTaskArgs: [],
      args: [],
      memoryBus: {},
      executeLogs: [],
      userInput: {},
      allUserInputs: [],
      executionSteps: [],
      tasks: [], // 新增任务数据
      execution_count: 0,
      errorMessage: '', // 用于存储错误消息
      isRun: false,
      inputDialogVisible: false,
      showErrorLog: false, // 控制错误日志的显示/隐藏
      /* 上传文件相关 */
      fileList: []
    }
  },
  computed: {
    notRunToEnd() {
      return this.nowOnTask < this.appDetail.task_list.length
    },
    runButtonMessage() {
      return (this.notRunToEnd ? '执行' : '重新执行')
    },
    executionCompleted() {
      return this.appDetail.task_list && this.nowOnTask >= this.appDetail.task_list.length
    }
  },
  created() {
    this.appId = this.$route.query.id
    this.getDetailAndShow()
  },
  methods: {
    getDetailAndShow() {
      getAppDetail(this.appId, this.$store.getters.id).then(res => {
        console.log('获取到的应用详情:', res)
        this.appDetail = res
        this.appName = res.app_name
        // 获取图片ID
        this.imageId = this.getImageId(this.appName)
        this.autoFillArgs(this.execution_count)
        // 获取任务数据
        // this.getWorkflowTasks();
      }).catch(error => {
        console.log('执行时获取详情出错:', error)
      })
    },
    getImageId(appName) {
      if (!appName || appName.length === 0) return 0
      const firstChar = appName[0].toUpperCase() // 取应用名称的首字母并转为大写
      const charCode = firstChar.charCodeAt(0) // 转换为字符编码
      return charCode % 20 // 对20取模，得到0-19
    },
    // 获取图片URL
    getImageUrl() {
      return require(`@/assets/icons/${this.imageId}.png`)
    },
    async autoFillArgs(task) {
      this.nowOnTask = task
      this.nowTaskContent = this.appDetail.task_list.at(task)
      this.nowTaskArgs = []
      this.args = this.nowTaskContent.parameters

      await getExecutroMemoryBus().then((res) => {
        this.memoryBus = res
      }).catch(error => {
        console.log('子组件填参', error)
      })

      console.log('-----', this.memoryBus)
      console.log('-----', this.args)

      this.args.forEach(arg => {
        // 使多选框默认不选中
        if (arg.input && arg.input.options && !this.isSingleChoice(arg.input.options)) {
          arg.value = [] // Initialize to empty array for multi-choice inputs
        }
        // 使input输入框的profile能够正确识别
        if (arg.input && !arg.input.options) {
          // 如果该值为profile.开头，则默认其为使用profile中的变量；如果没取到对应变量，则不进行改变
          try {
            if (arg.value.startsWith('profile')) {
              const keys = arg.value.split('.')
              let current = this.memoryBus
              for (const key of keys) {
                current = current[key]
              }
              arg.value = current
            }
          } catch (e) {
            console.log(e)
          }
        }
      })

      const hasInputArgs = this.args.some(arg => arg.source === 'input') || this.args.some(arg => arg.source === 'file')
      const step = {
        userInput: this.args,
        task_id: this.execution_count + 1,
        tool_name: this.nowTaskContent.tool_name,
        canceled: false
      }
      this.executionSteps.push(step)

      if (hasInputArgs) {
        this.inputDialogVisible = true
      } else {
        // console.log('提交表格')
        this.submitForm()
      }

      this.$nextTick(() => {
        this.scrollToInput()
      })
    },
    hasInputArgs(step) {
      // console.log('11111', step.userInput)
      // console.log('2222', step.userInput.some(arg => arg.source === 'file'))
      return step.userInput.some(arg => arg.source === 'input') || step.userInput.some(arg => arg.source === 'file')
    },
    isSingleChoice(options) {
      return options.some(option => option.hasOwnProperty('checked'))
    },
    async submitForm() {
      try {
        const res = await getExecutroMemoryBus()
        this.memoryBus = res
        this.args.forEach(arg => {
          if (arg.source === 'refer') {
            const path = arg.value.split('.')
            let value = this.memoryBus
            for (let i = 0; i < path.length; i++) {
              value = value[path[i]]
              if (value === undefined) break
            }
            arg.value = value
          }
        })

        const dataToSend = this.nowTaskContent.parameters.reduce((acc, arg) => {
          acc[arg.name] = arg.value
          return acc
        }, {})
        Object.keys(dataToSend).forEach(key => {
          const arg = this.args.find(arg => arg.name === key)
          if (arg) {
            arg.value = dataToSend[key]
          }
        })
        const userInput = this.args.reduce((acc, arg) => {
          if (arg.source === 'input') {
            acc[arg.name] = {
              value: arg.value,
              type: 'Input'
            }
          } else if (arg.source === 'const') {
            acc[arg.name] = {
              value: arg.value,
              type: 'Const'
            }
          } else if (arg.source === 'refer') {
            acc[arg.name] = {
              value: arg.value,
              type: 'Refer'
            }
          }
          return acc
        }, {})

        userInput.tool_name = this.nowTaskContent.tool_name
        const argsWithoutInput = this.args.map(arg => {
          return arg
        })

        this.userInput = userInput
        this.allUserInputs.push({ ...userInput })

        // Update the appDetail args without input
        this.appDetail.task_list.at(this.nowOnTask).parameters = argsWithoutInput
        console.log('发送的appDetail', this.appDetail)

        executeAppStep({ 'appDetail': this.appDetail, 'id': this.$store.getters.id }).then(response => {
          console.log('单步执行task：', response)
          this.executeLogs.push(response)
          this.nowOnTask += 1
          console.log('切换到下一个task:', this.nowOnTask)
          this.showChart()
          if (this.notRunToEnd) {
            this.autoFillArgs(this.nowOnTask)
          } else {
            // 所有任务已完成，滚动到页面底部
            this.scrollToCompletion()
          }
          // } else {
          //   this.$nextTick(() => {
          //     if (this.appDetail.code !== undefined) {
          //       console.log(this.appDetail.code);
          //       this.showChart();
          //     }
          //     // 滚动到页面底部
          //     this.scrollToCompletion();
          //   });
          // }
        }).catch(error => {
          if (!error.response.data.message) {
            this.errorMessage = '未知错误'
          } else {
            this.errorMessage = error.response.data.message
          }
          console.log('执行单步task失败：', error.response.data)
        })
        this.execution_count += 1
      } catch (error) {
        console.log('获取MemoryBus失败:', error)
      }

      this.$nextTick(() => {
        this.scrollToInput()
      })
    },
    cancelExecution(index) {
      this.executionSteps[index].canceled = true
    },
    showChart() {
      this.$nextTick(() => {
        const chartDom = document.getElementById(`chart-${this.nowOnTask - 1}`)
        const textContainer = document.getElementById(`text-${this.nowOnTask - 1}`)

        if (!chartDom) {
          console.error(`DOM element with ID "chart-${this.nowOnTask - 1}" not found.`)
          return
        }
        const myChart = echarts.init(chartDom)
        // 先将图表容器隐藏
        chartDom.style.display = 'none'
        textContainer.style.display = 'none'

        getExecutroMemoryBus().then(res => {
          const results = res.yf_processed_output.result
          const taskNum = this.nowOnTask - 1 // 当前任务编号
          if (results && results.length > 0) {
            this.memoryBusData[taskNum] = results
            this.memoryBusData[taskNum].forEach(item => {
              if (item.type === 'echart' && item.option) {
                // 如果是图表类型，设置图表的配置
                myChart.setOption(item.option)
                chartDom.style.display = 'block' // 显示图表
              } else if (item.type === 'text' && item.data) {
                // 如果是文本类型，展示文本内容
                if (textContainer) {
                  textContainer.innerHTML = item.data // 设置文本内容
                  textContainer.style.display = 'block' // 显示文本
                }
              }
            })
            this.scrollToCompletion()
            // console.log('getExecutroMemoryBus结果：', res.yf_processed_output.result.option);
            // myChart.setOption(res.yf_processed_output.result.option);
            // chartDom.style.display = 'block';  // 显示图表
          } else {
            console.warn('No chart option available.')
            chartDom.style.display = 'none' // 隐藏图表
            textContainer.style.display = 'none' // 隐藏文本
          }
        }).catch(error => {
          console.log('processOutput出错:', error)
          chartDom.style.display = 'none' // 隐藏图表
          textContainer.style.display = 'none' // 隐藏文本
        })
      })
    },
    scrollToCompletion() {
      this.$nextTick(() => {
        const target = this.$refs.completionMessage

        if (target) {
          const targetPosition = target.getBoundingClientRect().top + window.scrollY
          window.scrollTo({
            top: targetPosition,
            behavior: 'smooth' // 平滑滚动
          })
        } else {
          console.error('Target element not found')
        }
      })
    },
    scrollToInput() {
      this.$nextTick(() => {
        // Ensure that DOM updates have completed before trying to scroll
        const formItem = this.$el.querySelector('.el-form-item:last-of-type')
        if (formItem) {
          const top = formItem.getBoundingClientRect().top + window.scrollY
          window.scrollTo({
            top,
            behavior: 'smooth' // Smooth scrolling
          })
        } else {
          console.error('Form item not found')
        }
      })
    },
    toggleErrorLog() {
      this.showErrorLog = !this.showErrorLog // 切换错误日志显示状态
    },
    // 新增方法：获取任务数据
    getWorkflowTasks() {
      getWorkflow(this.appId).then(res => {
        console.log('获取到的任务数据:', res)
        this.tasks = res.tasks // 存储任务数据
      }).catch(error => {
        console.log('获取任务数据出错:', error)
      })
    },
    restartExecution() {
      this.memoryBusData = {} // 用来存储不同 taskNum 对应的 memoryBus 数据
      this.imageId = 0
      this.appDetail = {}
      this.appName = ''
      this.nowOnTask = 0
      this.nowTaskContent = {}
      this.nowTaskArgs = []
      this.args = []
      this.memoryBus = {}
      this.executeLogs = []
      this.userInput = {}
      this.allUserInputs = []
      this.executionSteps = []
      this.errorMessage = ''
      this.execution_count = 0
      this.isRun = false
      this.inputDialogVisible = false
      this.showErrorLog = false
      this.fileList = []
      this.file = null
      this.fileData = null
      this.formData = null
      this.img = null
      this.downloadLink = null
      this.getDetailAndShow() // 重新获取应用详情并初始化
    },
    // 上传文件的请求发送函数
    uploadFile(param) {
      const formData = new FormData()
      formData.append('file', param.file)
      uploadFile(formData).then(response => {
        console.log('上传文件成功', response)
        // 保存二进制格式的文件
        this.$emit('save-file', response)
        // 文件图标设为绿色
        param.onSuccess()
      }).catch(error => {
        console.log('上传文件失败', error)
        param.onError()
      })
    },
    // 移除上传文件的处理函数
    beforeRemoveFile(file, fileList) {
      return this.$confirm(`${this.$t('sure_remove_tip')}${file.name}?`)
    },
    // 上传文件个数超过限制的处理函数
    handleExceed(files, fileList) {
      this.$message.warning(`${this.$t('file_upload_tip_one')}，${this.$t('file_upload_tip_two')} ${files.length} ${this.$t('file_upload_tip_four')}，${this.$t('file_upload_tip_three')} ${files.length + fileList.length} ${this.$t('file_upload_tip_four')}`)
    }
  }
}
</script>

<style scoped>
.execute {
  width: 70%;
}

.logs {
  width: 30%;
}

.buttons {
  margin-top: 20px;
}

.center {
  margin: 0 auto;
  display: block;
}

.user {
  flex-direction: row;
}

.yuanfang {
  flex-direction: row-reverse;
}

.user-icon {
  position: absolute;
  right: 0;
  top: 0;
  margin: 10px;
  /* 根据需要调整 */
}

.content-wrapper {
  background-color: white;
  padding: 15px;

  /* 确保输入框不会被图片覆盖，可以根据图片的宽度进行调整 */
}

.user-avatar {
  cursor: pointer;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  margin-bottom: 5px;
}

.yuanfang-avatar {
  cursor: pointer;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  margin-bottom: 10px;
}

.button-container {
  display: flex;
  justify-content: center;
  margin-top: 10px;
}
</style>
